import { AfterContentInit, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { EzFormValidatorFn } from '../../utils';
import { EzFormComponent } from '../ez-form';
import { EzFormGroupComponent } from '../ez-form-group';
import { EzFormItemComponent } from '../ez-form-item';
import { EzFormControl } from './ez-form-control';
import { EzFormControlConfiguration } from './ez-form-control.configuration';

export abstract class EzFormControlComponent<C extends EzFormControlConfiguration = EzFormControlConfiguration, T = any>
  implements EzFormControl<T>, OnInit, AfterContentInit, OnDestroy {
  ezFormControlConfiguration: C;

  control: FormControl;

  constructor(
    protected ezForm: EzFormComponent,
    protected ezFormGroup: EzFormGroupComponent,
    protected ezFormItem: EzFormItemComponent
  ) {
    this.ezFormControlConfiguration = ezFormItem.ezFormItemConfiguration as C;
    this.control = ezFormItem.control;
    this.checkConfiguration(this.ezFormItem.ezFormItemConfiguration as C);
  }

  ngOnInit(): void {}

  ngAfterContentInit(): void {}

  ngOnDestroy(): void {}

  abstract checkConfiguration(configuration: C): void;

  enable(): void {
    this.control.enable();
  }

  disable(): void {
    this.control.disable();
  }

  isDisabled(): boolean {
    return this.control.disabled;
  }
  isEnabled(): boolean {
    return this.control.enabled;
  }

  isValid(): boolean {
    return this.control.valid;
  }

  hide(): void {
    this.ezFormControlConfiguration.hidden = true;
  }

  show(): void {
    this.ezFormControlConfiguration.hidden = false;
  }

  isVisible(): boolean {
    return !this.ezFormControlConfiguration.hidden;
  }

  setValue(value: any): void {
    this.control.setValue(value);
  }

  getValue(): T {
    return this.control.value;
  }

  validate(): void {
    this.control.markAsDirty();
    this.control.updateValueAndValidity();
  }

  markAsRequired(): void {
    this.ezFormControlConfiguration.required = true;
  }

  markAsNotRequired(): void {
    this.ezFormControlConfiguration.required = false;
  }

  setValidators(validators: EzFormValidatorFn[] = []): void {
    this.ezFormControlConfiguration.validators = validators;
    const validatorFnArray = [];
    validators.forEach(fn => {
      validatorFnArray.push(() => {
        return fn(this, this.ezFormGroup, this.ezForm);
      });
    });
    this.control.setValidators(validatorFnArray);
    this.control.markAsDirty();
    this.control.updateValueAndValidity();
  }
}
